package lk.icta.core.dao.impl;

import lk.icta.common.AppConstants;
import lk.icta.common.dao.impl.BaseDAO;
import lk.icta.common.web.WebConstants;
import lk.icta.core.dao.OrganizationDAO;
import lk.icta.core.entity.Organization;
import lk.icta.user.entity.User;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.Query;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author Tharanga Punchihewa
 */
public class OrganizationDAOImpl extends BaseDAO implements OrganizationDAO {

    @Transactional(propagation = Propagation.MANDATORY)
    public void addOrganization(Organization organization, User user) {
        logger.debug("Adding a Organization [Organization Name: {}\tUser: {}]", organization.getOrganizationNameEn());
        organization.getLifeCycleInfo().setCreatedUser(user);
        organization.getLifeCycleInfo().setCreatedTimeStamp(new Date());
        organization.getLifeCycleInfo().setLastUpdatedUser(user);
        organization.getLifeCycleInfo().setLastUpdatedTimeStamp(new Date());
        em.persist(organization);
    }

    @Transactional(propagation = Propagation.MANDATORY)
    public void updateOrganization(Organization organization, User user) {
        logger.debug("Updating  a Organization [Organization Name: {}\tUser: {}]", organization.getOrganizationNameEn());
        Organization existing = getOrganizationByIdUKey(organization.getId(), user);
        organization.getLifeCycleInfo().setCreatedUser(existing.getLifeCycleInfo().getCreatedUser());
        organization.getLifeCycleInfo().setCreatedTimeStamp(existing.getLifeCycleInfo().getLastUpdatedTimeStamp());
        organization.getLifeCycleInfo().setLastUpdatedUser(user);
        organization.getLifeCycleInfo().setLastUpdatedTimeStamp(new Date());
        em.merge(organization);
    }

    //update duedate
    @Transactional(propagation = Propagation.MANDATORY)
    public void updateDueDate(Organization organization, User user) {
        logger.debug("Updating  a Organization due date [Organization Name: {}\tUser: {}]", organization.getId());
        Organization existing = getOrganizationByIdUKey(organization.getId(), user);

        existing.setDueDate(organization.getDueDate());
        existing.setStatus(organization.getStatus());
        //existing.getLifeCycleInfo().setCreatedUser(existing.getLifeCycleInfo().getCreatedUser());
        //existing.getLifeCycleInfo().setCreatedTimeStamp(existing.getLifeCycleInfo().getLastUpdatedTimeStamp());
        existing.getLifeCycleInfo().setLastUpdatedUser(user);
        existing.getLifeCycleInfo().setLastUpdatedTimeStamp(new Date());
        em.merge(existing);
    }

    @Transactional(propagation = Propagation.MANDATORY)
    public Organization getOrganizationByIdUKey(int idUKey, User user) {
        logger.debug("Finding organization by idUkey : {}", idUKey);
        return em.find(Organization.class, idUKey);
    }

    @Transactional(propagation = Propagation.MANDATORY)
    public List<Organization> getAllOrganizations(User user) {
        Query q = em.createNamedQuery("getAllOrganizations");
        return q.getResultList();
    }


    @Transactional(propagation = Propagation.MANDATORY)
    public Map<Integer, String> getOrganizationListByLanguage(String language) {

        Query query = em.createQuery("SELECT o FROM Organization o");
        List<Organization> results = query.getResultList();

        Map<Integer, String> map = new HashMap<Integer, String>();

        for (Organization o : results) {
            String organizationName = "";
            if (AppConstants.ENGLISH.equals(language)) {
                organizationName = o.getOrganizationNameEn();
            } else if (AppConstants.SINHALA.equals(language)) {
                organizationName = o.getOrganizationNameSi();
            } else if (AppConstants.TAMIL.equals(language)) {
                organizationName = o.getOrganizationNameTa();
            }

            map.put(o.getId(), organizationName);
        }

        logger.debug("Loaded : {} Organization from the database", results.size());
        return map;
    }

    @Transactional(propagation = Propagation.MANDATORY)
    public List<Organization> getOrganizationListByType(Organization.Type type, User user) {
        Query q = em.createNamedQuery("getOrganizationListByType");
        q.setParameter("type", type);
        List result = q.getResultList();
        return result;
    }

    @Transactional(propagation = Propagation.MANDATORY)
    public List<Organization> getOrganizationListByStateAndType(Organization.State state, Organization.Type type, User user) {
        Query q = em.createNamedQuery("getOrganizationListByStateAndType");
        q.setParameter("type", type);
        q.setParameter("status", state);
        List result = q.getResultList();
        return result;
    }

    @Transactional(propagation = Propagation.MANDATORY)
    public List<Organization> getOrganizationListByState(Organization.State state) {
        Query q = em.createNamedQuery("getOrganizationListByState");
        q.setParameter("status", Organization.State.ACTIVE);
        List result = q.getResultList();
        return result;
    }
}
